<?php
namespace App\Common\Cla\Rbac\User;

use App\Common as com;

use App\Common\Cla\Rbac\User\Role as nameRole;
use App\Common\Cla\Rbac as nameRbac;

/**
 * @property nameRbac\User\DataStore $dataStore
 */
class Role extends com\Cla\ClaBase\CommonOfId\Client {

	/**
	 * Permission constructor.
	 * @param nameRbac\User\DataStore $dataStore
	 */
	public function __construct( nameRbac\User\DataStore $dataStore ) {
		parent::__construct( $dataStore );
	}

	/**
	 * @return com\Model\RbacUserRelation\DataManager
	 */
	public function goDirectDataManaerOfRead(  ):com\Model\RbacUserRelation\DataManager {
		return $this->goPool( __FUNCTION__, function(){
			return $this->goDirectDataManaer_New();
		} );
	}

	/**
	 * @return com\Model\RbacUserRelation\DataManager
	 */
	public function goDirectDataManaer_New(  ):com\Model\RbacUserRelation\DataManager {
		$rbacUserRelationDataManaer = com\Model\RbacUserRelation::dataManager();
		$rbacUserRelationDataManaer->whereEqData_UserType( $this->dataStore->main->getUserType() )
			->whereEqData_UserId( $this->dataStore->main->getUserId() )
			->whereEqData_RbacType( com\Model\RbacUserRelation::gosDataUnit()->goVar()->varRbacType_Role );
		//
		return $rbacUserRelationDataManaer;
	}

	/**
	 * 检查是否已授权（根据权限id）
	 * @param int $permissionId
	 * @return bool
	 */
	public function checkOfPermissionId( int $permissionId ):bool {
		// 获取用户绑定的 roleIds
		$rbacUserRelationDataUnit = com\Model\RbacUserRelation::dataUnit();
		$rbacUserRelationDataUnit->goWhereDy()->relationUser( $this->dataStore->main->getUserType(), $this->dataStore->main->getUserId() );
		$rbacUserRelationDataUnit->whereEqData_RbacType( com\Model\RbacUserRelation::gosDataUnit()->goVar()->varRbacType_Role );
		$roleIds = $rbacUserRelationDataUnit->value( 'rbac_ids', '' );
		$roleIds = com\Lib\Fun\Array_::toArray( $roleIds, [ 'setType' => 'int' ] );
		//
		return com\Cla\Rbac\Role::isExistPermissionIdsOfRoleIds( $roleIds, [ $permissionId ] );
	}

	/**
	 * 清除当前已绑定的权限缓存
	 * @return [true][必返]
	 */
	public function clearBindRoleIdsCache():bool {
		$this->dataStore->main->goToken()->session()->delOfPath( 'roleIds' );
		//
		return true;
	}

	/**
	 * 获取当前已绑定的权限（缓存）
	 * @param bool $force 是否强制从数据库中读取
	 * @return int[] 权限ids
	 */
	public function getBindRoleIdsOfCache( $force = false ):array {
		return com\Lib\Utils\ArrayHelper::trim( $this->getBindRoleIdsStrOfCache( $force ) )->toArrayHelper()->toArray();
	}

	/**
	 * 获取当前已绑定的权限（缓存）
	 * @param bool $force 是否强制从数据库中读取
	 * @return string 权限ids [逗号分割] [前后逗号]
	 */
	public function getBindRoleIdsStrOfCache( $force = false ) {
		// 读取缓存
		if( ! $force ){
			// @TODO :: 没设置缓存时间
			$permissionIds = $this->dataStore->main->goToken()->session()->getOfPath( 'roleIds' );
			if( $permissionIds !== false ) return $permissionIds;
		}
		// 读取数据库
		$rbacIds = $this->goDirectDataManaerOfRead()->value( 'rbac_ids', '' );
		// 保存到缓存
		$this->dataStore->main->goToken()->session()->setOfPath( 'roleIds', $rbacIds );
		//
		return $rbacIds;
	}

	/**
	 * 更新写入权限
	 * @param array $ckeckPermissionIdsArray
	 * @return bool 一定返回true
	 */
	private function updatePermissionIds( array $ckeckPermissionIdsArray ):bool {
		/*
		sort( $ckeckPermissionIdsArray );
		$ckeckPermissionIdsStr = implode( ",", $ckeckPermissionIdsArray );
		if( ! empty( $ckeckPermissionIdsStr ) ){
			$ckeckPermissionIdsStr = ",{$ckeckPermissionIdsStr},";
		}
		*/
		// 写入
		$modelDataUnit = $this->goDirectDataManaer_New();
		$modelDataUnit->newData_RbacIds()->setOfContinuousIds( $ckeckPermissionIdsArray );
		// $modelDataUnit->newData_RbacIds()->set( $ckeckPermissionIdsStr );
		$modelDataUnit->updateOrCreate();
		//
		$this->clearBindRoleIdsCache();
		//
		return true;
	}

	/**
	 * 绑定权限
	 * @param array $waitPermissionIds 需要绑定的权限ids
	 * @return bool 一定返回true
	 */
	public function binds( array $waitPermissionIds ):bool {
		// ...
		$permissionIdsStr = $this->getBindRoleIdsStrOfCache();
		$permissionIdsArray = com\Lib\Fun\Array_::toArray( $permissionIdsStr );
		$permissionIdsIndexArray = com\Lib\Fun\Array_::arrayFlip( $permissionIdsArray ); // 数组索引
		foreach( $waitPermissionIds as $permissionId ){
			if( isset( $permissionIdsIndexArray[ $permissionId ] ) == false ){
				// 加入
				$permissionIdsIndexArray[ $permissionId ] = 1;
			}
		}
		// 写入
		$this->updatePermissionIds( array_keys( $permissionIdsIndexArray ) );
		//
		return true;
	}

	/**
	 * 绑定权限（覆盖旧权限）
	 * @param array $waitPermissionIds 需要绑定的权限ids
	 * @return bool 一定返回true
	 */
	public function coverBinds( array $waitPermissionIds ) {
		// 写入
		$this->updatePermissionIds( $waitPermissionIds );
		//
		return true;
	}

	/**
	 * 解绑权限
	 * @param array $waitUnBindPermissionIds 需要解绑的权限ids
	 * @return bool 一定返回true
	 */
	public function unBinds( array $waitUnBindPermissionIds ):bool {
		// ...
		if( empty( $authSids ) ){
			throw com\Lib\Err\Exception::makeOfNew( '不能为空', com\Lib\Err\Code::$sysDataError );
		}
		//
		$permissionIdsStr = $this->getBindRoleIdsStrOfCache();
		$permissionIdsArray = com\Lib\Fun\Array_::toArray( $permissionIdsStr );
		$permissionIdsIndexArray = com\Lib\Fun\Array_::arrayFlip( $permissionIdsArray ); // 数组索引
		foreach( $waitUnBindPermissionIds as $waitUnBindPermissionId ){
			if( isset( $permissionIdsIndexArray[ $waitUnBindPermissionId ] ) ){
				// 加入
				unset( $permissionIdsIndexArray[ $waitUnBindPermissionId ] );
			}
		}
		// 写入
		$this->updatePermissionIds( array_keys( $permissionIdsIndexArray ) );
		//
		return true;
	}

	/**
	 * 是否已绑定指定权限
	 * @param array $ckeckPermissionIds 需要检查的权限ids
	 * @return bool
	 */
	public function isBinds( array $ckeckPermissionIds ):bool {
		// ...
		if( empty( $ckeckPermissionIds ) ){
			throw com\Lib\Err\Exception::makeOfNew( '不能为空', com\Lib\Err\Code::$sysDataError );
		}
		//
		$permissionIdsStr = $this->getBindRoleIdsStrOfCache();
		foreach( $ckeckPermissionIds as $permissionId ){
			if( strpos( $permissionIdsStr, ",{$permissionId}," ) == false ){
				return false;
			}
		}
		//
		return true;
	}

}
